home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / docmgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  27.3 KB  |  1,009 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_INIT_SEG
  14. #pragma code_seg(AFX_INIT_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. AFX_STATIC_DATA const TCHAR _afxShellOpenFmt[] = _T("%s\\shell\\open\\%s");
  23. AFX_STATIC_DATA const TCHAR _afxShellPrintFmt[] = _T("%s\\shell\\print\\%s");
  24. AFX_STATIC_DATA const TCHAR _afxShellPrintToFmt[] = _T("%s\\shell\\printto\\%s");
  25. AFX_STATIC_DATA const TCHAR _afxDefaultIconFmt[] = _T("%s\\DefaultIcon");
  26. AFX_STATIC_DATA const TCHAR _afxShellNewFmt[] = _T("%s\\ShellNew");
  27.  
  28. #define DEFAULT_ICON_INDEX 0
  29.  
  30. AFX_STATIC_DATA const TCHAR _afxIconIndexFmt[] = _T(",%d");
  31. AFX_STATIC_DATA const TCHAR _afxCommand[] = _T("command");
  32. AFX_STATIC_DATA const TCHAR _afxOpenArg[] = _T(" \"%1\"");
  33. AFX_STATIC_DATA const TCHAR _afxPrintArg[] = _T(" /p \"%1\"");
  34. AFX_STATIC_DATA const TCHAR _afxPrintToArg[] = _T(" /pt \"%1\" \"%2\" \"%3\" \"%4\"");
  35. AFX_STATIC_DATA const TCHAR _afxDDEArg[] = _T(" /dde");
  36.  
  37. AFX_STATIC_DATA const TCHAR _afxDDEExec[] = _T("ddeexec");
  38. AFX_STATIC_DATA const TCHAR _afxDDEOpen[] = _T("[open(\"%1\")]");
  39. AFX_STATIC_DATA const TCHAR _afxDDEPrint[] = _T("[print(\"%1\")]");
  40. AFX_STATIC_DATA const TCHAR _afxDDEPrintTo[] = _T("[printto(\"%1\",\"%2\",\"%3\",\"%4\")]");
  41.  
  42. AFX_STATIC_DATA const TCHAR _afxShellNewValueName[] = _T("NullFile");
  43. AFX_STATIC_DATA const TCHAR _afxShellNewValue[] = _T("");
  44.  
  45. // recursively remove a registry key if and only if it has no subkeys
  46.  
  47. BOOL AFXAPI _AfxDeleteRegKey(LPCTSTR lpszKey)
  48. {
  49.     // copy the string
  50.     LPTSTR lpszKeyCopy = _tcsdup(lpszKey);
  51.     LPTSTR lpszLast = lpszKeyCopy + lstrlen(lpszKeyCopy);
  52.  
  53.     // work until the end of the string
  54.     while (lpszLast != NULL)
  55.     {
  56.         *lpszLast = '\0';
  57.         lpszLast = _tcsdec(lpszKeyCopy, lpszLast);
  58.  
  59.         // try to open that key
  60.         HKEY hKey;
  61.         if (WCE_FCTN(RegOpenKey)(HKEY_CLASSES_ROOT, lpszKeyCopy, &hKey) != ERROR_SUCCESS)
  62.             break;
  63.  
  64.         // enumerate the keys underneath
  65.         TCHAR szScrap[_MAX_PATH+1];
  66.         DWORD dwLen = _countof(szScrap);
  67.         BOOL bItExists = FALSE;
  68.  
  69.         if (WCE_FCTN(RegEnumKey)(hKey, 0, szScrap, dwLen) == ERROR_SUCCESS)
  70.             bItExists = TRUE;
  71.         ::RegCloseKey(hKey);
  72.  
  73.         // found one?  quit looping
  74.         if (bItExists)
  75.             break;
  76.  
  77.         // otherwise, delete and find the previous backwhack
  78.         ::RegDeleteKey(HKEY_CLASSES_ROOT, lpszKeyCopy);
  79.         lpszLast = _tcsrchr(lpszKeyCopy, '\\');
  80.     }
  81.  
  82.     // release the string and return
  83.     free(lpszKeyCopy);
  84.     return TRUE;
  85. }
  86.  
  87. AFX_STATIC BOOL AFXAPI 
  88. _AfxSetRegKey(LPCTSTR lpszKey, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL)
  89. {
  90.     if (lpszValueName == NULL)
  91.     {
  92.         if (::WCE_FCTN(RegSetValue)(HKEY_CLASSES_ROOT, lpszKey, REG_SZ,
  93.               lpszValue, lstrlen(lpszValue) * sizeof(TCHAR)) != ERROR_SUCCESS)
  94.         {
  95.             TRACE1("Warning: registration database update failed for key '%s'.\n",
  96.                 lpszKey);
  97.             return FALSE;
  98.         }
  99.         return TRUE;
  100.     }
  101.     else
  102.     {
  103.         HKEY hKey;
  104.  
  105.         if(::WCE_FCTN(RegCreateKey)(HKEY_CLASSES_ROOT, lpszKey, &hKey) == ERROR_SUCCESS)
  106.         {
  107.             LONG lResult = ::RegSetValueEx(hKey, lpszValueName, 0, REG_SZ,
  108.                 (CONST BYTE*)lpszValue, (lstrlen(lpszValue) + 1) * sizeof(TCHAR));
  109.  
  110.             if(::RegCloseKey(hKey) == ERROR_SUCCESS && lResult == ERROR_SUCCESS)
  111.                 return TRUE;
  112.         }
  113.         TRACE1("Warning: registration database update failed for key '%s'.\n", lpszKey);
  114.         return FALSE;
  115.     }
  116. }
  117.  
  118. CDocManager::CDocManager()
  119. {
  120. }
  121.  
  122. #if !defined(_WIN32_WCE)
  123. void CDocManager::UnregisterShellFileTypes()
  124. {
  125.     ASSERT(!m_templateList.IsEmpty());  // must have some doc templates
  126.  
  127.     CString strPathName, strTemp;
  128.  
  129.     AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
  130.  
  131.     POSITION pos = m_templateList.GetHeadPosition();
  132.     for (int nTemplateIndex = 1; pos != NULL; nTemplateIndex++)
  133.     {
  134.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  135.  
  136.         CString strFilterExt, strFileTypeId, strFileTypeName;
  137.         if (pTemplate->GetDocString(strFileTypeId,
  138.            CDocTemplate::regFileTypeId) && !strFileTypeId.IsEmpty())
  139.         {
  140.             // enough info to register it
  141.             if (!pTemplate->GetDocString(strFileTypeName,
  142.                CDocTemplate::regFileTypeName))
  143.                 strFileTypeName = strFileTypeId;    // use id name
  144.  
  145.             ASSERT(strFileTypeId.Find(' ') == -1);  // no spaces allowed
  146.  
  147.             strTemp.Format(_afxDefaultIconFmt, (LPCTSTR)strFileTypeId);
  148.             _AfxDeleteRegKey(strTemp);
  149.  
  150.             // If MDI Application
  151.             if (!pTemplate->GetDocString(strTemp, CDocTemplate::windowTitle) ||
  152.                 strTemp.IsEmpty())
  153.             {
  154.                 // path\shell\open\ddeexec = [open("%1")]
  155.                 strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  156.                     (LPCTSTR)_afxDDEExec);
  157.                 _AfxDeleteRegKey(strTemp);
  158.  
  159.                 // path\shell\print\ddeexec = [print("%1")]
  160.                 strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  161.                     (LPCTSTR)_afxDDEExec);
  162.                 _AfxDeleteRegKey(strTemp);
  163.  
  164.                 // path\shell\printto\ddeexec = [printto("%1","%2","%3","%4")]
  165.                 strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  166.                     (LPCTSTR)_afxDDEExec);
  167.                 _AfxDeleteRegKey(strTemp);
  168.             }
  169.  
  170.             // path\shell\open\command = path filename
  171.             strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  172.                 (LPCTSTR)_afxCommand);
  173.             _AfxDeleteRegKey(strTemp);
  174.  
  175.             // path\shell\print\command = path /p filename
  176.             strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  177.                 (LPCTSTR)_afxCommand);
  178.             _AfxDeleteRegKey(strTemp);
  179.  
  180.             // path\shell\printto\command = path /pt filename printer driver port
  181.             strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  182.                 (LPCTSTR)_afxCommand);
  183.             _AfxDeleteRegKey(strTemp);
  184.  
  185.             pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt);
  186.             if (!strFilterExt.IsEmpty())
  187.             {
  188.                 ASSERT(strFilterExt[0] == '.');
  189.  
  190.                 LONG lSize = _MAX_PATH * 2;
  191.                 LONG lResult = ::RegQueryValue(HKEY_CLASSES_ROOT, strFilterExt,
  192.                     strTemp.GetBuffer(lSize), &lSize);
  193.                 strTemp.ReleaseBuffer();
  194.  
  195.                 if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() ||
  196.                     strTemp == strFileTypeId)
  197.                 {
  198.                     strTemp.Format(_afxShellNewFmt, (LPCTSTR)strFilterExt);
  199.                     _AfxDeleteRegKey(strTemp);
  200.  
  201.                     // no association for that suffix
  202.                     _AfxDeleteRegKey(strFilterExt);
  203.                 }
  204.             }
  205.         }
  206.     }
  207. }
  208.  
  209.  
  210. void CDocManager::RegisterShellFileTypes(BOOL bCompat)
  211. {
  212.     ASSERT(!m_templateList.IsEmpty());  // must have some doc templates
  213.  
  214.     CString strPathName, strTemp;
  215.  
  216.     AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
  217.  
  218.     POSITION pos = m_templateList.GetHeadPosition();
  219.     for (int nTemplateIndex = 1; pos != NULL; nTemplateIndex++)
  220.     {
  221.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  222.  
  223.         CString strOpenCommandLine = strPathName;
  224.         CString strPrintCommandLine = strPathName;
  225.         CString strPrintToCommandLine = strPathName;
  226.         CString strDefaultIconCommandLine = strPathName;
  227.  
  228.         if (bCompat)
  229.         {
  230.             CString strIconIndex;
  231.             HICON hIcon = ::ExtractIcon(AfxGetInstanceHandle(), strPathName, nTemplateIndex);
  232.             if (hIcon != NULL)
  233.             {
  234.                 strIconIndex.Format(_afxIconIndexFmt, nTemplateIndex);
  235.                 DestroyIcon(hIcon);
  236.             }
  237.             else
  238.             {
  239.                 strIconIndex.Format(_afxIconIndexFmt, DEFAULT_ICON_INDEX);
  240.             }
  241.             strDefaultIconCommandLine += strIconIndex;
  242.         }
  243.  
  244.         CString strFilterExt, strFileTypeId, strFileTypeName;
  245.         if (pTemplate->GetDocString(strFileTypeId,
  246.            CDocTemplate::regFileTypeId) && !strFileTypeId.IsEmpty())
  247.         {
  248.             // enough info to register it
  249.             if (!pTemplate->GetDocString(strFileTypeName,
  250.                CDocTemplate::regFileTypeName))
  251.                 strFileTypeName = strFileTypeId;    // use id name
  252.  
  253.             ASSERT(strFileTypeId.Find(' ') == -1);  // no spaces allowed
  254.  
  255.             // first register the type ID of our server
  256.             if (!_AfxSetRegKey(strFileTypeId, strFileTypeName))
  257.                 continue;       // just skip it
  258.  
  259.             if (bCompat)
  260.             {
  261.                 // path\DefaultIcon = path,1
  262.                 strTemp.Format(_afxDefaultIconFmt, (LPCTSTR)strFileTypeId);
  263.                 if (!_AfxSetRegKey(strTemp, strDefaultIconCommandLine))
  264.                     continue;       // just skip it
  265.             }
  266.  
  267.             // If MDI Application
  268.             if (!pTemplate->GetDocString(strTemp, CDocTemplate::windowTitle) ||
  269.                 strTemp.IsEmpty())
  270.             {
  271.                 // path\shell\open\ddeexec = [open("%1")]
  272.                 strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  273.                     (LPCTSTR)_afxDDEExec);
  274.                 if (!_AfxSetRegKey(strTemp, _afxDDEOpen))
  275.                     continue;       // just skip it
  276.  
  277.                 if (bCompat)
  278.                 {
  279.                     // path\shell\print\ddeexec = [print("%1")]
  280.                     strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  281.                         (LPCTSTR)_afxDDEExec);
  282.                     if (!_AfxSetRegKey(strTemp, _afxDDEPrint))
  283.                         continue;       // just skip it
  284.  
  285.                     // path\shell\printto\ddeexec = [printto("%1","%2","%3","%4")]
  286.                     strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  287.                         (LPCTSTR)_afxDDEExec);
  288.                     if (!_AfxSetRegKey(strTemp, _afxDDEPrintTo))
  289.                         continue;       // just skip it
  290.  
  291.                     // path\shell\open\command = path /dde
  292.                     // path\shell\print\command = path /dde
  293.                     // path\shell\printto\command = path /dde
  294.                     strOpenCommandLine += _afxDDEArg;
  295.                     strPrintCommandLine += _afxDDEArg;
  296.                     strPrintToCommandLine += _afxDDEArg;
  297.                 }
  298.                 else
  299.                 {
  300.                     strOpenCommandLine += _afxOpenArg;
  301.                 }
  302.             }
  303.             else
  304.             {
  305.                 // path\shell\open\command = path filename
  306.                 // path\shell\print\command = path /p filename
  307.                 // path\shell\printto\command = path /pt filename printer driver port
  308.                 strOpenCommandLine += _afxOpenArg;
  309.                 if (bCompat)
  310.                 {
  311.                     strPrintCommandLine += _afxPrintArg;
  312.                     strPrintToCommandLine += _afxPrintToArg;
  313.                 }
  314.             }
  315.  
  316.             // path\shell\open\command = path filename
  317.             strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  318.                 (LPCTSTR)_afxCommand);
  319.             if (!_AfxSetRegKey(strTemp, strOpenCommandLine))
  320.                 continue;       // just skip it
  321.  
  322.             if (bCompat)
  323.             {
  324.                 // path\shell\print\command = path /p filename
  325.                 strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  326.                     (LPCTSTR)_afxCommand);
  327.                 if (!_AfxSetRegKey(strTemp, strPrintCommandLine))
  328.                     continue;       // just skip it
  329.  
  330.                 // path\shell\printto\command = path /pt filename printer driver port
  331.                 strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  332.                     (LPCTSTR)_afxCommand);
  333.                 if (!_AfxSetRegKey(strTemp, strPrintToCommandLine))
  334.                     continue;       // just skip it
  335.             }
  336.  
  337.             pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt);
  338.             if (!strFilterExt.IsEmpty())
  339.             {
  340.                 ASSERT(strFilterExt[0] == '.');
  341.  
  342.                 LONG lSize = _MAX_PATH * 2;
  343.                 LONG lResult = ::RegQueryValue(HKEY_CLASSES_ROOT, strFilterExt,
  344.                     strTemp.GetBuffer(lSize), &lSize);
  345.                 strTemp.ReleaseBuffer();
  346.  
  347.                 if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() ||
  348.                     strTemp == strFileTypeId)
  349.                 {
  350.                     // no association for that suffix
  351.                     if (!_AfxSetRegKey(strFilterExt, strFileTypeId))
  352.                         continue;
  353.  
  354.                     if (bCompat)
  355.                     {
  356.                         strTemp.Format(_afxShellNewFmt, (LPCTSTR)strFilterExt);
  357.                         (void)_AfxSetRegKey(strTemp, _afxShellNewValue, _afxShellNewValueName);
  358.                     }
  359.                 }
  360.             }
  361.         }
  362.     }
  363. }
  364. #endif // _WIN32_WCE
  365.  
  366. #ifdef AFX_CORE3_SEG
  367. #pragma code_seg(AFX_CORE3_SEG)
  368. #endif
  369.  
  370. AFX_STATIC void AFXAPI _AfxAppendFilterSuffix(CString& filter, OPENFILENAME& ofn,
  371.     CDocTemplate* pTemplate, CString* pstrDefaultExt)
  372. {
  373.     ASSERT_VALID(pTemplate);
  374.     ASSERT_KINDOF(CDocTemplate, pTemplate);
  375.  
  376.     CString strFilterExt, strFilterName;
  377.     if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) &&
  378.      !strFilterExt.IsEmpty() &&
  379.      pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
  380.      !strFilterName.IsEmpty())
  381.     {
  382.         // a file based document template - add to filter list
  383.         ASSERT(strFilterExt[0] == '.');
  384.         if (pstrDefaultExt != NULL)
  385.         {
  386.             // set the default extension
  387.             *pstrDefaultExt = ((LPCTSTR)strFilterExt) + 1;  // skip the '.'
  388.             ofn.lpstrDefExt = (LPTSTR)(LPCTSTR)(*pstrDefaultExt);
  389.             ofn.nFilterIndex = ofn.nMaxCustFilter + 1;  // 1 based number
  390.         }
  391.  
  392.         // add to filter
  393.         filter += strFilterName;
  394.         ASSERT(!filter.IsEmpty());  // must have a file type name
  395.         filter += (TCHAR)'\0';  // next string please
  396.         filter += (TCHAR)'*';
  397.         filter += strFilterExt;
  398.         filter += (TCHAR)'\0';  // next string please
  399.         ofn.nMaxCustFilter++;
  400.     }
  401. }
  402.  
  403. // Get the best document template for the named file
  404.  
  405. class CNewTypeDlg : public CDialog
  406. {
  407. protected:
  408.     CPtrList*   m_pList;        // actually a list of doc templates
  409. public:
  410.     CDocTemplate*   m_pSelectedTemplate;
  411.  
  412. public:
  413.     //{{AFX_DATA(CNewTypeDlg)
  414.     enum { IDD = AFX_IDD_NEWTYPEDLG };
  415.     //}}AFX_DATA
  416.     CNewTypeDlg(CPtrList* pList) : CDialog(CNewTypeDlg::IDD)
  417.     {
  418.         m_pList = pList;
  419.         m_pSelectedTemplate = NULL;
  420.     }
  421.     ~CNewTypeDlg() { }
  422.  
  423. protected:
  424.     BOOL OnInitDialog();
  425.     void OnOK();
  426.     //{{AFX_MSG(CNewTypeDlg)
  427.     //}}AFX_MSG
  428.     DECLARE_MESSAGE_MAP()
  429. };
  430.  
  431. BEGIN_MESSAGE_MAP(CNewTypeDlg, CDialog)
  432.     //{{AFX_MSG_MAP(CNewTypeDlg)
  433.     ON_LBN_DBLCLK(AFX_IDC_LISTBOX, OnOK)
  434.     //}}AFX_MSG_MAP
  435. END_MESSAGE_MAP()
  436.  
  437. BOOL CNewTypeDlg::OnInitDialog()
  438. {
  439.     CListBox* pListBox = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  440.     ASSERT(pListBox != NULL);
  441.  
  442.     // fill with document templates in list
  443.     pListBox->ResetContent();
  444.  
  445.     POSITION pos = m_pList->GetHeadPosition();
  446.     // add all the CDocTemplates in the list by name
  447.     while (pos != NULL)
  448.     {
  449.         CDocTemplate* pTemplate = (CDocTemplate*)m_pList->GetNext(pos);
  450.         ASSERT_KINDOF(CDocTemplate, pTemplate);
  451.  
  452.         CString strTypeName;
  453.         if (pTemplate->GetDocString(strTypeName, CDocTemplate::fileNewName) &&
  454.            !strTypeName.IsEmpty())
  455.         {
  456.             // add it to the listbox
  457.             int nIndex = pListBox->AddString(strTypeName);
  458.             if (nIndex == -1)
  459.             {
  460.                 EndDialog(-1);
  461.                 return FALSE;
  462.             }
  463.             pListBox->SetItemDataPtr(nIndex, pTemplate);
  464.         }
  465.     }
  466.  
  467.     int nTemplates = pListBox->GetCount();
  468.     if (nTemplates == 0)
  469.     {
  470.         TRACE0("Error: no document templates to select from!\n");
  471.         EndDialog(-1); // abort
  472.     }
  473.     else if (nTemplates == 1)
  474.     {
  475.         // get the first/only item
  476.         m_pSelectedTemplate = (CDocTemplate*)pListBox->GetItemDataPtr(0);
  477.         ASSERT_VALID(m_pSelectedTemplate);
  478.         ASSERT_KINDOF(CDocTemplate, m_pSelectedTemplate);
  479.         EndDialog(IDOK);    // done
  480.     }
  481.     else
  482.     {
  483.         // set selection to the first one (NOT SORTED)
  484.         pListBox->SetCurSel(0);
  485.     }
  486.  
  487.     return CDialog::OnInitDialog();
  488. }
  489.  
  490. void CNewTypeDlg::OnOK()
  491. {
  492.     CListBox* pListBox = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  493.     ASSERT(pListBox != NULL);
  494.     // if listbox has selection, set the selected template
  495.     int nIndex;
  496.     if ((nIndex = pListBox->GetCurSel()) == -1)
  497.     {
  498.         // no selection
  499.         m_pSelectedTemplate = NULL;
  500.     }
  501.     else
  502.     {
  503.         m_pSelectedTemplate = (CDocTemplate*)pListBox->GetItemDataPtr(nIndex);
  504.         ASSERT_VALID(m_pSelectedTemplate);
  505.         ASSERT_KINDOF(CDocTemplate, m_pSelectedTemplate);
  506.     }
  507.     CDialog::OnOK();
  508. }
  509.  
  510. /////////////////////////////////////////////////////////////////////////////
  511. // CDocManager
  512.  
  513. void CDocManager::AddDocTemplate(CDocTemplate* pTemplate)
  514. {
  515.     if (pTemplate == NULL)
  516.     {
  517.         if (pStaticList != NULL)
  518.         {
  519.             POSITION pos = pStaticList->GetHeadPosition();
  520.             while (pos != NULL)
  521.             {
  522.                 CDocTemplate* pTemplate =
  523.                     (CDocTemplate*)pStaticList->GetNext(pos);
  524.                 AddDocTemplate(pTemplate);
  525.             }
  526.             delete pStaticList;
  527.             pStaticList = NULL;
  528.         }
  529.         bStaticInit = FALSE;
  530.     }
  531.     else
  532.     {
  533.         ASSERT_VALID(pTemplate);
  534.         ASSERT(m_templateList.Find(pTemplate, NULL) == NULL);// must not be in list
  535.         pTemplate->LoadTemplate();
  536.         m_templateList.AddTail(pTemplate);
  537.     }
  538. }
  539.  
  540. POSITION CDocManager::GetFirstDocTemplatePosition() const
  541. {
  542.     return m_templateList.GetHeadPosition();
  543. }
  544.  
  545. CDocTemplate* CDocManager::GetNextDocTemplate(POSITION& pos) const
  546. {
  547.     return (CDocTemplate*)m_templateList.GetNext(pos);
  548. }
  549.  
  550. BOOL CDocManager::SaveAllModified()
  551. {
  552.     POSITION pos = m_templateList.GetHeadPosition();
  553.     while (pos != NULL)
  554.     {
  555.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  556.         ASSERT_KINDOF(CDocTemplate, pTemplate);
  557.         if (!pTemplate->SaveAllModified())
  558.             return FALSE;
  559.     }
  560.     return TRUE;
  561. }
  562.  
  563. void CDocManager::CloseAllDocuments(BOOL bEndSession)
  564. {
  565.     POSITION pos = m_templateList.GetHeadPosition();
  566.     while (pos != NULL)
  567.     {
  568.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  569.         ASSERT_KINDOF(CDocTemplate, pTemplate);
  570.         pTemplate->CloseAllDocuments(bEndSession);
  571.     }
  572. }
  573.  
  574. BOOL CDocManager::DoPromptFileName(CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate)
  575. {
  576.     CFileDialog dlgFile(bOpenFileDialog);
  577.  
  578.     CString title;
  579.     VERIFY(title.LoadString(nIDSTitle));
  580.  
  581.     dlgFile.m_ofn.Flags |= lFlags;
  582.  
  583.     CString strFilter;
  584.     CString strDefault;
  585.     if (pTemplate != NULL)
  586.     {
  587.         ASSERT_VALID(pTemplate);
  588.         _AfxAppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, &strDefault);
  589.     }
  590.     else
  591.     {
  592.         // do for all doc template
  593.         POSITION pos = m_templateList.GetHeadPosition();
  594.         BOOL bFirst = TRUE;
  595.         while (pos != NULL)
  596.         {
  597.             CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  598.             _AfxAppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate,
  599.                 bFirst ? &strDefault : NULL);
  600.             bFirst = FALSE;
  601.         }
  602.     }
  603.  
  604.     // append the "*.*" all files filter
  605.     CString allFilter;
  606.     VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
  607.     strFilter += allFilter;
  608.     strFilter += (TCHAR)'\0';   // next string please
  609.     strFilter += _T("*.*");
  610.     strFilter += (TCHAR)'\0';   // last string
  611.     dlgFile.m_ofn.nMaxCustFilter++;
  612.  
  613.     dlgFile.m_ofn.lpstrFilter = strFilter;
  614.     dlgFile.m_ofn.lpstrTitle = title;
  615.     dlgFile.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH);
  616.  
  617.     int nResult = dlgFile.DoModal();
  618.     fileName.ReleaseBuffer();
  619.     return nResult == IDOK;
  620. }
  621.  
  622. int CDocManager::GetDocumentCount()
  623. {
  624.     // count all documents
  625.     int nCount = 0;
  626.     POSITION pos = m_templateList.GetHeadPosition();
  627.     while (pos != NULL)
  628.     {
  629.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  630.         POSITION pos2 = pTemplate->GetFirstDocPosition();
  631.         while (pos2 != NULL)
  632.         {
  633.             pTemplate->GetNextDoc(pos2);
  634.             ++nCount;
  635.         }
  636.     }
  637.     return nCount;
  638. }
  639.  
  640. BOOL CDocManager::OnDDECommand(LPTSTR lpszCommand)
  641. {
  642.     CString strCommand = lpszCommand;
  643.     CDocument* pDoc = NULL;
  644.  
  645.     // open format is "[open("%s")]" - no whitespace allowed, one per line
  646.     // print format is "[print("%s")]" - no whitespace allowed, one per line
  647.     // print to format is "[printto("%s","%s","%s","%s")]" - no whitespace allowed, one per line
  648.     CCommandLineInfo cmdInfo;
  649.     cmdInfo.m_nShellCommand = CCommandLineInfo::FileDDE;
  650.  
  651.     if (strCommand.Left(7) == _T("[open(\""))
  652.     {
  653.         cmdInfo.m_nShellCommand = CCommandLineInfo::FileOpen;
  654.         strCommand = strCommand.Right(strCommand.GetLength() - 7);
  655.     }
  656. #if !defined(_WIN32_WCE_NO_PRINTING)
  657.     else if (strCommand.Left(8) == _T("[print(\""))
  658.     {
  659.         cmdInfo.m_nShellCommand = CCommandLineInfo::FilePrint;
  660.         strCommand = strCommand.Right(strCommand.GetLength() - 8);
  661.     }
  662.     else if (strCommand.Left(10) == _T("[printto(\""))
  663.     {
  664.         cmdInfo.m_nShellCommand = CCommandLineInfo::FilePrintTo;\
  665.         strCommand = strCommand.Right(strCommand.GetLength() - 10);
  666.     }
  667. #endif // _WIN32_WCE_NO_PRINTING
  668.     else
  669.         return FALSE; // not a command we handle
  670.  
  671.     int i = strCommand.Find('"');
  672.     if (i == -1)
  673.         return FALSE; // illegally terminated
  674.  
  675.     cmdInfo.m_strFileName = strCommand.Left(i);
  676.     strCommand = strCommand.Right(strCommand.GetLength() - i);
  677.  
  678.     CCommandLineInfo* pOldInfo = NULL;
  679.     BOOL bRetVal = TRUE;
  680.  
  681.     // If we were started up for DDE retrieve the Show state
  682.     if (AfxGetApp()->m_pCmdInfo != NULL)
  683.     {
  684.         AfxGetApp()->m_nCmdShow = (int)AfxGetApp()->m_pCmdInfo;
  685.         AfxGetApp()->m_pCmdInfo = &cmdInfo;
  686.     }
  687.     else
  688.         pOldInfo = AfxGetApp()->m_pCmdInfo;
  689.  
  690.     if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen)
  691.     {
  692.         // show the application window
  693.         CWnd* pMainWnd = AfxGetApp()->m_pMainWnd;
  694.         int nCmdShow = AfxGetApp()->m_nCmdShow;
  695.         if (nCmdShow == -1 || nCmdShow == SW_SHOWNORMAL)
  696.         {
  697.             if (pMainWnd->IsIconic())
  698.                 nCmdShow = SW_RESTORE;
  699.             else
  700.                 nCmdShow = SW_SHOW;
  701.         }
  702.         pMainWnd->ShowWindow(nCmdShow);
  703.         if (nCmdShow != SW_MINIMIZE)
  704.             pMainWnd->SetForegroundWindow();
  705.  
  706.         // then open the document
  707.         AfxGetApp()->OpenDocumentFile(cmdInfo.m_strFileName);
  708.  
  709. #if !defined(_WIN32_WCE_NO_OLE)
  710.         // user is now "in control" of the application
  711.         if (!AfxOleGetUserCtrl())
  712.             AfxOleSetUserCtrl(TRUE);
  713. #endif // _WIN32_WCE_NO_OLE
  714.  
  715.         // next time, show the window as default
  716.         AfxGetApp()->m_nCmdShow = -1;
  717.         goto RestoreAndReturn;
  718.     }
  719.  
  720. #if !defined(_WIN32_WCE)
  721.     if (cmdInfo.m_nShellCommand == CCommandLineInfo::FilePrintTo)
  722.     {
  723.         if (strCommand.Left(3) != _T("\",\""))
  724.         {
  725.             bRetVal = FALSE;
  726.             goto RestoreAndReturn;
  727.         }
  728.         else
  729.         {
  730.             strCommand = strCommand.Right(strCommand.GetLength() - 3);
  731.             i = strCommand.Find('"');
  732.             if (i == -1)
  733.             {
  734.                 bRetVal = FALSE;
  735.                 goto RestoreAndReturn;
  736.             }
  737.             else
  738.             {
  739.                 cmdInfo.m_strPrinterName = strCommand.Left(i);
  740.                 strCommand = strCommand.Right(strCommand.GetLength() - i);
  741.             }
  742.         }
  743.  
  744.         if (strCommand.Left(3) != _T("\",\""))
  745.         {
  746.             bRetVal = FALSE;
  747.             goto RestoreAndReturn;
  748.         }
  749.         else
  750.         {
  751.             strCommand = strCommand.Right(strCommand.GetLength() - 3);
  752.             i = strCommand.Find('"');
  753.             if (i == -1)
  754.             {
  755.                 bRetVal = FALSE;
  756.                 goto RestoreAndReturn;
  757.             }
  758.             else
  759.             {
  760.                 cmdInfo.m_strDriverName = strCommand.Left(i);
  761.                 strCommand = strCommand.Right(strCommand.GetLength() - i);
  762.             }
  763.         }
  764.  
  765.         if (strCommand.Left(3) != _T("\",\""))
  766.         {
  767.             bRetVal = FALSE;
  768.             goto RestoreAndReturn;
  769.         }
  770.         else
  771.         {
  772.             strCommand = strCommand.Right(strCommand.GetLength() - 3);
  773.             i = strCommand.Find('"');
  774.             if (i == -1)
  775.             {
  776.                 bRetVal = FALSE;
  777.                 goto RestoreAndReturn;
  778.             }
  779.             else
  780.             {
  781.                 cmdInfo.m_strPortName = strCommand.Left(i);
  782.                 strCommand = strCommand.Right(strCommand.GetLength() - i);
  783.             }
  784.         }
  785.     }
  786. #endif // _WIN32_WCE
  787.  
  788.     // get document count before opening it
  789.     int nOldCount; nOldCount = GetDocumentCount();
  790.  
  791.     // open the document, then print it.
  792.     pDoc = AfxGetApp()->OpenDocumentFile(cmdInfo.m_strFileName);
  793.     AfxGetApp()->m_pCmdInfo = &cmdInfo;
  794.     AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);
  795.     AfxGetApp()->m_pCmdInfo = NULL;
  796.  
  797.     // close the document if it wasn't open previously (based on doc count)
  798.     if (GetDocumentCount() > nOldCount)
  799.         pDoc->OnCloseDocument();
  800.  
  801. #if !defined(_WIN32_WCE_NO_OLE)
  802.      // if the app was only started to process this command then close
  803.      if (!AfxOleGetUserCtrl())
  804.         AfxGetApp()->m_pMainWnd->PostMessage(WM_CLOSE);
  805. #endif // _WIN32_WCE_NO_OLE
  806.  
  807. RestoreAndReturn:
  808.     AfxGetApp()->m_pCmdInfo = pOldInfo;
  809.     return bRetVal;
  810. }
  811.  
  812. void CDocManager::OnFileNew()
  813. {
  814.     if (m_templateList.IsEmpty())
  815.     {
  816.         TRACE0("Error: no document templates registered with CWinApp.\n");
  817.         AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
  818.         return;
  819.     }
  820.  
  821.     CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
  822.     if (m_templateList.GetCount() > 1)
  823.     {
  824.         // more than one document template to choose from
  825.         // bring up dialog prompting user
  826.         CNewTypeDlg dlg(&m_templateList);
  827.         int nID = dlg.DoModal();
  828.         if (nID == IDOK)
  829.             pTemplate = dlg.m_pSelectedTemplate;
  830.         else
  831.             return;     // none - cancel operation
  832.     }
  833.  
  834.     ASSERT(pTemplate != NULL);
  835.     ASSERT_KINDOF(CDocTemplate, pTemplate);
  836.  
  837.     pTemplate->OpenDocumentFile(NULL);
  838.         // if returns NULL, the user has already been alerted
  839. }
  840.  
  841. void CDocManager::OnFileOpen()
  842. {
  843.     // prompt the user (with all document templates)
  844.     CString newName;
  845.     if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
  846.       OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
  847.         return; // open cancelled
  848.  
  849.     AfxGetApp()->OpenDocumentFile(newName);
  850.         // if returns NULL, the user has already been alerted
  851. }
  852.  
  853. #ifdef _DEBUG
  854. void CDocManager::AssertValid() const
  855. {
  856.     CObject::AssertValid();
  857.  
  858.     POSITION pos = m_templateList.GetHeadPosition();
  859.     while (pos != NULL)
  860.     {
  861.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  862.         ASSERT_VALID(pTemplate);
  863.     }
  864. }
  865.  
  866. void CDocManager::Dump(CDumpContext& dc) const
  867. {
  868.     CObject::Dump(dc);
  869.  
  870.     if (dc.GetDepth() != 0)
  871.     {
  872.         dc << "\nm_templateList[] = {";
  873.         POSITION pos = m_templateList.GetHeadPosition();
  874.         while (pos != NULL)
  875.         {
  876.             CDocTemplate* pTemplate =
  877.                 (CDocTemplate*)m_templateList.GetNext(pos);
  878.             dc << "\ntemplate " << pTemplate;
  879.         }
  880.         dc << "}";
  881.     }
  882.  
  883.     dc << "\n";
  884. }
  885. #endif
  886.  
  887. #ifdef AFX_CORE2_SEG
  888. #pragma code_seg(AFX_CORE2_SEG)
  889. #endif
  890.  
  891. CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)
  892. {
  893.     // find the highest confidence
  894.     POSITION pos = m_templateList.GetHeadPosition();
  895.     CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;
  896.     CDocTemplate* pBestTemplate = NULL;
  897.     CDocument* pOpenDocument = NULL;
  898.  
  899.     TCHAR szPath[_MAX_PATH];
  900.     ASSERT(lstrlen(lpszFileName) < _countof(szPath));
  901.     TCHAR szTemp[_MAX_PATH];
  902.     if (lpszFileName[0] == '\"')
  903.         ++lpszFileName;
  904.     lstrcpyn(szTemp, lpszFileName, _MAX_PATH);
  905.     LPTSTR lpszLast = _tcsrchr(szTemp, '\"');
  906.     if (lpszLast != NULL)
  907.         *lpszLast = 0;
  908.     AfxFullPath(szPath, szTemp);
  909.     TCHAR szLinkName[_MAX_PATH];
  910.     if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))
  911.         lstrcpy(szPath, szLinkName);
  912.  
  913.     while (pos != NULL)
  914.     {
  915.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  916.         ASSERT_KINDOF(CDocTemplate, pTemplate);
  917.  
  918.         CDocTemplate::Confidence match;
  919.         ASSERT(pOpenDocument == NULL);
  920.         match = pTemplate->MatchDocType(szPath, pOpenDocument);
  921.         if (match > bestMatch)
  922.         {
  923.             bestMatch = match;
  924.             pBestTemplate = pTemplate;
  925.         }
  926.         if (match == CDocTemplate::yesAlreadyOpen)
  927.             break;      // stop here
  928.     }
  929.  
  930.     if (pOpenDocument != NULL)
  931.     {
  932.         POSITION pos = pOpenDocument->GetFirstViewPosition();
  933.         if (pos != NULL)
  934.         {
  935.             CView* pView = pOpenDocument->GetNextView(pos); // get first one
  936.             ASSERT_VALID(pView);
  937.             CFrameWnd* pFrame = pView->GetParentFrame();
  938.             if (pFrame != NULL)
  939.                 pFrame->ActivateFrame();
  940.             else
  941.                 TRACE0("Error: Can not find a frame for document to activate.\n");
  942.             CFrameWnd* pAppFrame;
  943.             if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))
  944.             {
  945.                 ASSERT_KINDOF(CFrameWnd, pAppFrame);
  946.                 pAppFrame->ActivateFrame();
  947.             }
  948.         }
  949.         else
  950.         {
  951.             TRACE0("Error: Can not find a view for document to activate.\n");
  952.         }
  953.         return pOpenDocument;
  954.     }
  955.  
  956.     if (pBestTemplate == NULL)
  957.     {
  958.         AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);
  959.         return NULL;
  960.     }
  961.  
  962.     return pBestTemplate->OpenDocumentFile(szPath);
  963. }
  964.  
  965. int CDocManager::GetOpenDocumentCount()
  966. {
  967.     int nOpen = 0;
  968.     POSITION pos = m_templateList.GetHeadPosition();
  969.     while (pos != NULL)
  970.     {
  971.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  972.         POSITION pos2 = pTemplate->GetFirstDocPosition();
  973.         while (pos2)
  974.         {
  975.             if (pTemplate->GetNextDoc(pos2) != NULL)
  976.                 nOpen++;
  977.         }
  978.     }
  979.     return nOpen;
  980. }
  981.  
  982. #ifdef AFX_TERM_SEG
  983. #pragma code_seg(AFX_TERM_SEG)
  984. #endif
  985.  
  986. CDocManager::~CDocManager()
  987. {
  988.     // for cleanup - delete all document templates
  989.     POSITION pos = m_templateList.GetHeadPosition();
  990.     while (pos != NULL)
  991.     {
  992.         POSITION posTemplate = pos;
  993.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  994.         if (pTemplate->m_bAutoDelete)
  995.         {
  996.             m_templateList.RemoveAt(posTemplate);
  997.             delete (CDocTemplate*)pTemplate;
  998.         }
  999.     }
  1000. }
  1001.  
  1002. #ifdef AFX_INIT_SEG
  1003. #pragma code_seg(AFX_INIT_SEG)
  1004. #endif
  1005.  
  1006. IMPLEMENT_DYNAMIC(CDocManager, CObject)
  1007.  
  1008. /////////////////////////////////////////////////////////////////////////////
  1009.